/*  Copyright (C) 2008  Alexander Blyzniuchenko (BlezAlex)

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using System.Text;
using System.Windows.Forms;
using DC;
using MediaDC.Native;

namespace MediaDC.Forms
{
    public partial class FileListForm : Form
    {
        private readonly FileListing _fl;
        private string _curPath = string.Empty;
        private readonly string _nickName;
        private readonly int _hubConnectionID;
        private const string EXPANDING_ITEM = "Expanding";

        public FileListForm(int hubConnectionID, string nickName, FileListing listing)
        {
            InitializeComponent();

            _nickName = nickName;
            _hubConnectionID = hubConnectionID;
            _fl = listing;

            NativeImageList.SetListViewIconIndex(directoryView.Handle);
            directoryView.SetExStyles();

            directoryTree.ImageIndex = NativeImageList.DirectoryIconIndex;
            directoryTree.SelectedImageIndex = NativeImageList.DirectoryIconIndex;

            directoryTree.BeginUpdate();
            directoryTree.Nodes.Clear();
            directoryTree.Nodes.Add(DcDirectory.PATH_SEPARATOR,_nickName);
            directoryTree.Nodes[0].Nodes.Add(EXPANDING_ITEM);
            LoadNodeData(directoryTree.Nodes[0], _curPath);
            directoryTree.EndUpdate();
            NativeImageList.SetTreeViewIconIndex(directoryTree.Handle);
        }

        public override string Text
        {
            get { return _nickName; }
            set { throw new NotSupportedException(); }
        }

        private void SelectNodeByPath(string k)
        {
            if (!string.IsNullOrEmpty(k))
            {

                TreeNode[] res = directoryTree.Nodes.Find(_curPath, true);
                if (res.Length > 0 )
                    LoadNodeData(res[0], _curPath);

                TreeNode[] c = directoryTree.Nodes.Find(k, true);
                if (c.Length > 0)
                {
                    TreeNode n = (TreeNode)c.GetValue(0);
                    directoryTree.SelectedNode = n;
                    directoryTree.Select();
                }
            }
        }

        private void LoadNodeData(TreeNode node, string path)
        {
            if (node.Nodes.Count == 0)
                return;

            if (node.Nodes.Count != 1 || node.Nodes[0].Text != EXPANDING_ITEM)
                return;

            DcDirectory curDir = _fl[path];

            node.Nodes.Clear();
            curDir.Directories.Sort(delegate(DcDirectory d1, DcDirectory d2)
                                 {
                                     return d1.Name.CompareTo(d2.Name);
                                 });

            foreach (DcDirectory d in curDir.Directories)
            {
                string curPath = path + DcDirectory.PATH_SEPARATOR + d.Name;
                node.Nodes.Add(curPath, d.Name);
                TreeNode n = node.LastNode;
                if (d.Directories.Count > 0)
                    n.Nodes.Add(EXPANDING_ITEM);
            }
        }

        private static string ExtractPath(TreeNode node)
        {
            string path = node.FullPath;

            if (path.Contains(DcDirectory.PATH_SEPARATOR))
                path = path.Remove(0, path.IndexOf(DcDirectory.PATH_SEPARATOR));
            else
                path = string.Empty;
            return path;
        }

        private void directoryTree_BeforeExpand(object sender, TreeViewCancelEventArgs e)
        {
            TreeNode node = e.Node;
            LoadNodeData(node, ExtractPath(e.Node));
        }

        private void directoryTree_AfterSelect(object sender, TreeViewEventArgs e)
        {
            directoryView.BeginUpdate();
            directoryView.Items.Clear();

            _curPath = ExtractPath(e.Node);

            foreach (DcDirectory d in _fl[_curPath].Directories)
                directoryView.Items.Add(new DirectoryItem(d));

            foreach (DcFile f in _fl[_curPath].Files)
                directoryView.Items.Add(new FileItem(f));

            directoryView.EndUpdate();
        }

        private void directoryView_DoubleClick(object sender, EventArgs e)
        {
            if (directoryView.SelectedItems.Count == 0)
                return;

            FileListItem item = (FileListItem)directoryView.SelectedItems[0];

            SelectNodeByPath(_curPath + DcDirectory.PATH_SEPARATOR + item.Name);
            if (item is FileItem)
            {
                DcFile file = ((FileItem) item).File;
                PreviewManager.RunPreview(file, _nickName, _hubConnectionID);
            }
        }

        private void directoryView_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == '\r')
                directoryView_DoubleClick(sender, EventArgs.Empty);
        }


        private void directoryView_ItemDrag(object sender, ItemDragEventArgs e)
        {
            string[] urls = new string[directoryView.SelectedItems.Count];
            StringBuilder text = new StringBuilder(urls.Length * 200); // A magic number :) I think 200 characters is enouth to contain an URL;

            for (int i = 0; i < directoryView.SelectedItems.Count; i++)
            {
                FileListItem item = (FileListItem)directoryView.SelectedItems[i];
                if (item is DirectoryItem)
                {
                    MessageBox.Show("You can not drag folders");
                    return;
                }

                DcFile file = ((FileItem) item).File;
                urls[i] = PreviewManager.GetPreviewUrl(_nickName, _hubConnectionID, file.TTH);
                text.AppendLine(urls[i]);
            }

            DataObject data = new DataObject(DataFormats.FileDrop, urls);
            data.SetText(text.ToString());
            DoDragDrop(data, DragDropEffects.Copy | DragDropEffects.Link);
        }
    }
}
